/*
    Copyright (C) 2019 Zongming Liu <1849059316@qq.com>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include "Font.h"
#include "../base/GameWorld.h"
#include "../render/IDirectRender.h"

namespace SkyEngine2d
{

    Font::Font(const std::wstring &family, int pointSize /*= -1*/, Font::FONT_WEIGHT weight /*= -1*/, bool italic /*= false*/)
        : m_fontFamily(family), m_fontSize(pointSize), m_fontWeight(weight), m_fontStyle(Font::defultFontStyle), m_fontStretch(Font::defultFontStretch), m_fontLocaleName(Font::defultFontLocalName), m_isWordWrapping(false), m_isDirty(false), m_alignment(AlignCenter)
    {
        init();
    }

    Font::Font(const Font &font)
    {
    }

    Font::Font()
        : m_fontFamily(Font::defultFontFamily), m_fontSize(Font::defultFontSize), m_fontWeight(Font::defultFontWeight), m_fontStyle(Font::defultFontStyle), m_fontStretch(Font::defultFontStretch), m_fontLocaleName(Font::defultFontLocalName), m_isWordWrapping(false), m_isDirty(false), m_alignment(AlignCenter)
    {
        init();
    }

    Font::FONT_STYLE Font::getFontStyle() const
    {
        return m_fontStyle;
    }

    Font::FONT_STRETCH Font::getFontStretch() const
    {
        return m_fontStretch;
    }

    const std::wstring &Font::getFontFamily() const
    {
        return m_fontFamily;
    }

    const std::wstring &Font::getLocaleName() const
    {
        return m_fontLocaleName;
    }

    float Font::getFontSize() const
    {
        return m_fontSize;
    }

    const Size &Font::getFontPixelSize() const
    {
        return m_fontPixelSize;
    }

    int Font::getFontWeight() const
    {
        return m_fontWeight;
    }

    void Font::setWordWrapping(bool wordWrapping /*= true*/)
    {
        m_isWordWrapping = wordWrapping;
        auto v = wordWrapping ? DWRITE_WORD_WRAPPING_WRAP : DWRITE_WORD_WRAPPING_NO_WRAP;
        m_format->SetWordWrapping(v);
    }

    bool Font::isWordWrapping() const
    {
        return m_isWordWrapping;
    }

    void Font::setAlignment(int flag)
    {
        m_alignment = flag;
        if (flag & AlignHCenter)
        {
            m_format->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT::DWRITE_PARAGRAPH_ALIGNMENT_CENTER);
        }
        if (flag & AlignVCenter)
        {
            m_format->SetTextAlignment(DWRITE_TEXT_ALIGNMENT::DWRITE_TEXT_ALIGNMENT_CENTER);
        }
        if (flag & AlignLeft)
        {
            m_format->SetTextAlignment(DWRITE_TEXT_ALIGNMENT::DWRITE_TEXT_ALIGNMENT_LEADING);
        }
        if (flag & AlignRight)
        {
            m_format->SetTextAlignment(DWRITE_TEXT_ALIGNMENT::DWRITE_TEXT_ALIGNMENT_TRAILING);
        }
        if (flag & AlignTop)
        {
            m_format->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT::DWRITE_PARAGRAPH_ALIGNMENT_NEAR);
        }
        if (flag & AlignBottom)
        {
            m_format->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT::DWRITE_PARAGRAPH_ALIGNMENT_FAR);
        }
    }

    bool Font::operator==(const Font &font) const
    {
        return m_fontStyle == font.m_fontStyle &&
               m_fontWeight == font.m_fontWeight &&
               m_fontStretch == font.m_fontStretch &&
               m_fontSize == font.m_fontSize &&
               m_fontPixelSize == font.m_fontPixelSize &&
               m_fontFamily == font.m_fontFamily &&
               m_fontLocaleName == font.m_fontLocaleName;
    }

    Microsoft::WRL::ComPtr<IDWriteFactory> Font::getWriteFactory()
    {
        if (s_dwFactory == nullptr)
        {
            DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory),
                                reinterpret_cast<IUnknown **>(s_dwFactory.GetAddressOf()));
        }
        return s_dwFactory;
    }

    void Font::init()
    {
        Font::getWriteFactory()->CreateTextFormat(
            getFontFamily().c_str(),
            nullptr,
            static_cast<DWRITE_FONT_WEIGHT>(getFontWeight()),
            static_cast<DWRITE_FONT_STYLE>(getFontStyle()),
            static_cast<DWRITE_FONT_STRETCH>(getFontStretch()),
            getFontSize(),
            getLocaleName().c_str(),
            m_format.ReleaseAndGetAddressOf());

        m_fontSize = m_format->GetFontSize();
        auto dpi = GameWorld::getInstance()->getDirectInterface()->getDpi();
        // m_fontPixelSize.width = dpi.x / 160 * m_fontSize;
        // m_fontPixelSize.height = dpi.y / 160 * m_fontSize;

        this->setWordWrapping(m_isWordWrapping);
        this->setAlignment(m_alignment);
    }

    Microsoft::WRL::ComPtr<IDWriteTextFormat> Font::getFormt()
    {
        if (m_isDirty)
        {
            init();
            m_isDirty = false;
        }
        return m_format;
    }

    const std::wstring Font::defultFontFamily = L"宋体";

    const std::wstring Font::defultFontLocalName = L"zh-cn";

    const Font::FONT_STYLE Font::defultFontStyle = Font::FONT_STYLE::NORMAL;

    const Font::FONT_STRETCH Font::defultFontStretch = Font::FONT_STRETCH::NORMAL;

    const float Font::defultFontSize = 18;

    const int Font::defultFontWeight = Font::FONT_WEIGHT::FONT_WEIGHT_NORMAL;

    Microsoft::WRL::ComPtr<IDWriteFactory> Font::s_dwFactory;
}
